<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      img {
        width: 100%;
        display: block;
      }
    </style>
  </head>

  <body>
    <input type="file" name="" id="file" accept="image/*" />
    <div>
      <button id="grayscale">灰度图</button>
      <button id="sepia">复古效果</button>
      <button id="red">红色蒙版</button>
      <button id="brightness">亮度效果</button>
      <button id="invert">反转效果</button>
    </div>

    <img src="" alt="" />
    <script>
      // 灰度图（grayscale）就是取红、绿、蓝三个像素值的算术平均值，这实际上将图像转成了黑白形式。
      function grayscale(pixels) {
        var d = pixels.data;
        for (var i = 0; i < d.length; i += 4) {
          var r = d[i];
          var g = d[i + 1];
          var b = d[i + 2];
          d[i] = d[i + 1] = d[i + 2] = (r + g + b) / 3;
        }
        return pixels;
      }
      // 复古效果（sepia）是将红、绿、蓝三种值，分别取这三个值的某种加权平均值，使得图像有一种古旧的效果。
      function sepia(pixels) {
        var d = pixels.data;
        for (var i = 0; i < d.length; i += 4) {
          var r = d[i];
          var g = d[i + 1];
          var b = d[i + 2];
          d[i] = r * 0.393 + g * 0.769 + b * 0.189; // red
          d[i + 1] = r * 0.349 + g * 0.686 + b * 0.168; // green
          d[i + 2] = r * 0.272 + g * 0.534 + b * 0.131; // blue
        }
        return pixels;
      }
      // 红色蒙版指的是，让图像呈现一种偏红的效果。算法是将红色通道设为红、绿、蓝三个值的平均值，而将绿色通道和蓝色通道都设为0。
      function red(pixels) {
        var d = pixels.data;
        for (var i = 0; i < d.length; i += 4) {
          var r = d[i];
          var g = d[i + 1];
          var b = d[i + 2];
          d[i] = (r + g + b) / 3; // 红色通道取平均值
          d[i + 1] = d[i + 2] = 0; // 绿色通道和蓝色通道都设为0
        }
        return pixels;
      }
      // 亮度效果（brightness）是指让图像变得更亮或更暗。算法将红色通道、绿色通道、蓝色通道，同时加上一个正值或负值。
      function brightness(pixels, delta) {
        var d = pixels.data;
        for (var i = 0; i < d.length; i += 4) {
          d[i] += delta; // red
          d[i + 1] += delta; // green
          d[i + 2] += delta; // blue
        }
        return pixels;
      }
      // 反转效果（invert）是指图片呈现一种色彩颠倒的效果。算法为红、绿、蓝通道都取各自的相反值（255 - 原值）
      function invert(pixels) {
        var d = pixels.data;
        for (var i = 0; i < d.length; i += 4) {
          d[i] = 255 - d[i];
          d[i + 1] = 255 - d[i + 1];
          d[i + 2] = 255 - d[i + 2];
        }
        return pixels;
      }
    </script>
    <script>
      const file = document.querySelector("#file");
      let context = null;
      let app = null;
      const img = document.querySelector("img");
      document.querySelector("#grayscale").addEventListener("click", () => {
        if (!context) {
          return alert("请选择图片");
        }
        let imageData = context.getImageData(0, 0, app.width, app.height);
        imageData = grayscale(imageData);
        context.putImageData(imageData, 0, 0);
        const base64 = app.toDataURL("image/jpeg", 1);
        console.log("base64Data", base64);
        img.setAttribute("src", base64);
      });
      document.querySelector("#sepia").addEventListener("click", () => {
        if (!context) {
          return alert("请选择图片");
        }
        let imageData = context.getImageData(0, 0, app.width, app.height);
        imageData = sepia(imageData);
        context.putImageData(imageData, 0, 0);
        const base64 = app.toDataURL("image/jpeg", 1);
        img.setAttribute("src", base64);
        console.log("base64Data", base64);
      });
      document.querySelector("#red").addEventListener("click", () => {
        if (!context) {
          return alert("请选择图片");
        }
        let imageData = context.getImageData(0, 0, app.width, app.height);
        imageData = red(imageData);
        context.putImageData(imageData, 0, 0);
        const base64 = app.toDataURL("image/jpeg", 1);
        img.setAttribute("src", base64);
        console.log("base64Data", base64);
      });
      document.querySelector("#brightness").addEventListener("click", () => {
        if (!context) {
          return alert("请选择图片");
        }
        let imageData = context.getImageData(0, 0, app.width, app.height);
        imageData = brightness(imageData);
        context.putImageData(imageData, 0, 0);
        const base64 = app.toDataURL("image/jpeg", 1);
        console.log("base64Data", base64);
        img.setAttribute("src", base64);
      });
      document.querySelector("#invert").addEventListener("click", () => {
        if (!context) {
          return alert("请选择图片");
        }
        let imageData = context.getImageData(0, 0, app.width, app.height);
        imageData = invert(imageData);
        context.putImageData(imageData, 0, 0);
        const base64 = app.toDataURL("image/jpeg", 1);
        console.log("base64Data", base64);
        img.setAttribute("src", base64);
      });
      file.addEventListener("change", (e) => {
        if (e.target.files.length > 0) {
          const blob = e.target.files[0];
          const url = window.URL.createObjectURL(blob);
          app = document.createElement("canvas");
          context = app.getContext("2d");
          const img = new Image();
          img.src = url;
          img.addEventListener("load", () => {
            console.log(img, img.width, img.height);
            const height = Number(img.height);
            const width = Number(img.width);
            app.width = width;
            app.height = height;
            context.drawImage(img, 0, 0);
          });
        }
      });
    </script>
  </body>
</html>
